import yaml
import re
from functools import wraps

def recursive_replace(data, context):
    """递归替换数据中的占位符"""
    if isinstance(data, dict):
        return {k: recursive_replace(v, context) for k, v in data.items()}
    elif isinstance(data, list):
        return [recursive_replace(item, context) for item in data]
    elif isinstance(data, str):
        # 处理完整占位符（返回原始类型）
        full_placeholder = re.match(r"^{{\s*(\w+)\s*}}$", data)
        if full_placeholder:
            key = full_placeholder.group(1)
            return context.get(key, data)
        
        # 处理字符串中的嵌入占位符
        def replace_match(match):
            key = match.group(1).strip()
            return str(context.get(key, match.group(0)))
        
        return re.sub(r"{{\s*(\w+)\s*}}", replace_match, data)
    return data

def yaml_param_loader(yaml_path):
    """装饰器：加载YAML文件并用函数参数替换占位符"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 1. 读取YAML文件
            with open(yaml_path, 'r') as f:
                raw_data = yaml.safe_load(f)
            
            # 2. 合并参数（优先使用函数参数）
            context = {}
            if hasattr(func, 'default_context'):
                context.update(func.default_context)
            context.update(kwargs)
            
            # 3. 递归替换占位符
            processed_data = recursive_replace(raw_data, context)
            
            # 4. 调用原函数并传递处理后的数据
            return func(processed_data, *args, **kwargs)
        return wrapper
    return decorator

# 可选：设置默认参数的类装饰器
class Defaults:
    def __init__(self, **defaults):
        self.default_context = defaults
    
    def __call__(self, func):
        func.default_context = self.default_context
        return func
    


# 定义默认参数（可选）
@Defaults(feature1="Login", email="default@example.com")  # process_config = (Defaults(xxx))(process_config)
@yaml_param_loader("config.yaml")
def process_config(config_data, extra_param):
    print("Received extra param:", extra_param)
    print("Processed config:")
    print(yaml.dump(config_data, allow_unicode=True))

# 调用函数（动态替换参数）
# process_config(
#     extra_param="hello",
#     user_name="张三",
#     age=30,
#     feature2="Payment"
# )